package com.xunwulian.web.controller.frame;

import com.alibaba.dubbo.config.annotation.Reference;
import com.google.gson.Gson;
import com.xunwulian.api.iface.ConfigAPI;
import com.xunwulian.api.iface.MenuAPI;
import com.xunwulian.api.iface.SmsAPI;
import com.xunwulian.api.iface.UserAPI;
import com.xunwulian.base.dao.RoleDao;
import com.xunwulian.base.entity.*;
import com.xunwulian.base.util.DateUtil;
import com.xunwulian.base.util.PageData;
import com.xunwulian.base.util.SysUtils;
import com.xunwulian.web.controller.BaseController;
import com.xunwulian.web.util.AppUtil;
import com.xunwulian.web.util.Const;
import com.xunwulian.web.util.PasswordUtil;
import com.xunwulian.web.util.RightsHelper;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Controller
public class LoginController extends BaseController {

    @Reference
    private MenuAPI menuAPI;
    @Reference
    private UserAPI userAPI;
    @Reference
    private ConfigAPI configAPI;
    @Reference
    private SmsAPI smsAPI;

    @Autowired
    private RoleDao roleDao;

    /**
     * 获取登录用户的IP
     */
    public void getRemortIP(String userName) {
        HttpServletRequest request = this.getRequest();
        String ip = "";
        if (request.getHeader("x-forwarded-for") == null) {
            ip = request.getRemoteAddr();
        } else {
            ip = request.getHeader("x-forwarded-for");
        }
        userAPI.saveIP(ip, userName);
    }

    /**
     * 访问首页
     */
    @GetMapping(value = "/")
    public String index() {
        ModelAndView mv = this.getModelAndView();
        try {
            PageData pd = this.getPageData();
//            pd.put("SYSNAME", configAPI.getByCode("sys_name").getValue()); // 读取系统名称
            mv.setViewName("index");
            mv.addObject("pd", pd);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "index";
    }

    /**
     * 访问登录页
     */
    @GetMapping(value = "/login_toLogin")
    public ModelAndView toLogin() {
        ModelAndView mv = this.getModelAndView();
        try {
            PageData pd = this.getPageData();
//            pd.put("SYSNAME", configAPI.getByCode("sys_name").getValue()); // 读取系统名称
            mv.setViewName("system/admin/login");
            mv.addObject("pd", pd);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return mv;
    }

    /**
     * 请求登录，验证用户
     */
    @ResponseBody
    @RequestMapping(value = "/login_login", produces = "application/json;charset=UTF-8")
    public Object login() {
        Map<String, String> map = new HashMap<String, String>();
        PageData pd = this.getPageData();
        String errInfo = "";

        String KEYDATA[] = pd.getString("KEYDATA")
                .replaceAll("qq290119597fh", "")
                .replaceAll("QQ290119597fh", "").split(",fh,");

        if (null != KEYDATA && KEYDATA.length == 3) {
            // shiro管理的session
            Session session = SecurityUtils.getSubject().getSession();
            String sessionCode = (String) session.getAttribute(Const.SESSION_SECURITY_CODE); // 获取session中的验证码

            String code = KEYDATA[2];
            String userName = KEYDATA[0];
            String password = KEYDATA[1];

            if (StringUtils.isBlank(code)) {
                errInfo = "nullcode"; // 验证码为空
            } else {
                if (StringUtils.isNotBlank(sessionCode) && sessionCode.equalsIgnoreCase(code)) {
                    String passwdEncrypt = PasswordUtil.getPassword(userName, password); // 密码加密
                    User user = userAPI.getUserByNameAndPwd(userName, passwdEncrypt);
                    if (user != null) {
                        try {
                            // shiro加入身份验证
                            Subject subject = SecurityUtils.getSubject();
                            UsernamePasswordToken token = new UsernamePasswordToken(
                                    userName, password);
                            subject.login(token);
                            session.setAttribute(Const.SESSION_USER, user);
                        } catch (AuthenticationException e) {
                            errInfo = "身份验证失败！";
                        }

                        String lastLogin = DateUtil.getTime();
                        user.setLAST_LOGIN(lastLogin);
                        userAPI.updateLastLogin(lastLogin, user.getUSER_ID());
                        session.setAttribute(Const.SESSION_USER, user);
                        session.removeAttribute(Const.SESSION_SECURITY_CODE);
                    } else {
                        errInfo = "usererror"; // 用户名或密码有误
                    }
                } else {
                    errInfo = "codeerror"; // 验证码输入有误
                }
                if (SysUtils.isEmpty(errInfo)) {
                    errInfo = "success"; // 验证成功
                }
            }
        } else {
            errInfo = "error"; // 缺少参数
        }
        map.put("result", errInfo);
        return AppUtil.returnObject(new PageData(), map);
    }

    /**
     * 访问系统首页
     */
    @RequestMapping(value = "/main/{changeMenu}")
    public ModelAndView login_index(@PathVariable("changeMenu") String changeMenu) {
        ModelAndView mv = this.getModelAndView();
        PageData pd = this.getPageData();
        try {
            // shiro管理的session
            Subject currentUser = SecurityUtils.getSubject();
            Session session = currentUser.getSession();

            User user = (User) session.getAttribute(Const.SESSION_USER);
            if (user != null) {
                Role role = roleDao.getRoleById(user.getROLE_ID());
                String roleRights = role != null ? role.getRIGHTS() : "";
                // 避免每次拦截用户操作时查询数据库，以下将用户所属角色权限、用户权限限都存入session
                session.setAttribute(Const.SESSION_ROLE_RIGHTS, roleRights); // 将角色权限存入session
                session.setAttribute(Const.SESSION_USERNAME, user.getUSERNAME()); // 放入用户名

                List<Menu> allmenuList;
                if (null == session.getAttribute(Const.SESSION_allmenuList)) {
                    allmenuList = menuAPI.listAllMenu();
                    if (SysUtils.notEmpty(roleRights)) {
                        RightsHelper.updateMenuRights(roleRights, allmenuList);
                    }
                    session.setAttribute(Const.SESSION_allmenuList, allmenuList); // 菜单权限放入session中
                } else {
                    allmenuList = (List<Menu>) session.getAttribute(Const.SESSION_allmenuList);
                }

                // 切换菜单
                List<Menu> menuList;
                if (null == session.getAttribute(Const.SESSION_menuList) || ("yes".equals(changeMenu))) {
                    List<Menu> menuList1 = new ArrayList<>();
                    List<Menu> menuList2 = new ArrayList<>();

                    // 拆分菜单
                    for (int i = 0; i < allmenuList.size(); i++) {
                        Menu menu = allmenuList.get(i);
                        if ("1".equals(menu.getMENU_TYPE())) {
                            menuList1.add(menu);
                        } else {
                            menuList2.add(menu);
                        }
                    }

                    session.removeAttribute(Const.SESSION_menuList);
                    if ("2".equals(session.getAttribute("changeMenu"))) {
                        session.setAttribute(Const.SESSION_menuList, menuList1);
                        session.removeAttribute("changeMenu");
                        session.setAttribute("changeMenu", "1");
                        menuList = menuList1;
                    } else {
                        session.setAttribute(Const.SESSION_menuList, menuList2);
                        session.removeAttribute("changeMenu");
                        session.setAttribute("changeMenu", "2");
                        menuList = menuList2;
                    }
                } else {
                    menuList = (List<Menu>) session.getAttribute(Const.SESSION_menuList);
                }

                // 切换菜单, 按钮权限放到session中
                if (null == session.getAttribute(Const.SESSION_QX)) {
                    session.setAttribute(Const.SESSION_QX, this.getUQX(session));
                }

                // 读取websocket配置
                String strWEBSOCKET = configAPI.getByCode("websocket").getValue();
                if (null != strWEBSOCKET && !"".equals(strWEBSOCKET)) {
                    String strIW[] = strWEBSOCKET.split(",fh,");
                    if (strIW.length == 4) {
                        pd.put("WIMIP", strIW[0]);
                        pd.put("WIMPORT", strIW[1]);
                        pd.put("OLIP", strIW[2]);
                        pd.put("OLPORT", strIW[3]);
                    }
                }

                mv.setViewName("system/admin/index");
                mv.addObject("user", user);
                mv.addObject("menuList", menuList);
            } else {
                mv.setViewName("system/admin/login");// session失效后跳转登录页面
            }

        } catch (Exception e) {
            mv.setViewName("system/admin/login");
            logger.error(e.getMessage(), e);
        }
        pd.put("SYSNAME", configAPI.getByCode("sys_name").getValue()); // 读取系统名称
        mv.addObject("pd", pd);
        return mv;
    }

    /**
     * 进入tab标签
     *
     * @return
     */
    @RequestMapping(value = "/tab")
    public String tab() {
        return "system/admin/tab";
    }

    /**
     * 进入首页后的默认页面
     *
     * @return
     */
    @RequestMapping(value = "/login_default")
    public ModelAndView defaultPage() {
        ModelAndView mv = this.getModelAndView();
        List<String> hotList = new ArrayList<>();
        try {
            // 从session获取用户信息
            Subject currentUser = SecurityUtils.getSubject();
            Session session = currentUser.getSession();
            User user = (User) session.getAttribute(Const.SESSION_USER);
            String userId = user.getUSER_ID();

            hotList = (List<String>) smsAPI.getHostList(userId).getData();
            logger.debug("hotList:" + new Gson().toJson(hotList));
        } catch (Exception e) {
            e.printStackTrace();
        }
        mv.addObject("hotList", hotList);
        mv.setViewName("system/smspocessor/smspocessor");
        return mv;
    }

    /**
     * 用户注销
     *
     * @return
     */
    @RequestMapping(value = "/logout")
    public ModelAndView logout() {
        ModelAndView mv = this.getModelAndView();
        PageData pd = this.getPageData();
        try {
            // shiro管理的session
            Subject currentUser = SecurityUtils.getSubject();
            Session session = currentUser.getSession();

            session.removeAttribute(Const.SESSION_USER);
            session.removeAttribute(Const.SESSION_ROLE_RIGHTS);
            session.removeAttribute(Const.SESSION_allmenuList);
            session.removeAttribute(Const.SESSION_menuList);
            session.removeAttribute(Const.SESSION_QX);
            session.removeAttribute(Const.SESSION_userpds);
            session.removeAttribute(Const.SESSION_USERNAME);
            session.removeAttribute(Const.SESSION_USERROL);
            session.removeAttribute("changeMenu");

            // shiro销毁登录
            Subject subject = SecurityUtils.getSubject();
            subject.logout();

            String msg = pd.getString("msg");
            pd.put("msg", msg);

            pd.put("SYSNAME", configAPI.getByCode("sys_name").getValue()); // 读取系统名称
            mv.setViewName("system/admin/login");
            mv.addObject("pd", pd);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return mv;
    }

    /**
     * 获取用户权限
     *
     * @param session
     * @return
     */
    public Map<String, String> getUQX(Session session) {
        Map<String, String> map = new HashMap<String, String>();
        try {
            String userName = session.getAttribute(Const.SESSION_USERNAME).toString();
            String ROLE_ID = userAPI.getByName(userName).getROLE_ID();
            Role role = roleDao.findById(ROLE_ID);

            GLQXEntity glqxEntity = roleDao.findGLbyrid(ROLE_ID);
            if (glqxEntity != null) {
                map.put("FX_QX", glqxEntity.getFxqx());
                map.put("FW_QX", glqxEntity.getFwqx());
                map.put("QX1", glqxEntity.getQx1());
                map.put("QX2", glqxEntity.getQx2());
                map.put("QX3", glqxEntity.getQx3());
                map.put("QX4", glqxEntity.getQx4());

                HYQXEntity hyqxEntity = roleDao.findYHbyrid(ROLE_ID);
                map.put("C1", hyqxEntity.getC1());
                map.put("C2", hyqxEntity.getC2());
                map.put("C3", hyqxEntity.getC3());
                map.put("C4", hyqxEntity.getC4());
                map.put("Q1", hyqxEntity.getQ1());
                map.put("Q2", hyqxEntity.getQ2());
                map.put("Q3", hyqxEntity.getQ3());
                map.put("Q4", hyqxEntity.getQ4());
            }

            map.put("adds", role.getADD_QX());
            map.put("dels", role.getDEL_QX());
            map.put("edits", role.getEDIT_QX());
            map.put("chas", role.getCHA_QX());

            logger.info("获取用户权限，" + new Gson().toJson(map));
            this.getRemortIP(userName);
        } catch (Exception e) {
            logger.error(e.toString(), e);
        }
        return map;
    }
}
